﻿using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System.ComponentModel.DataAnnotations;

namespace DoNet.ORM.Repository.Repository
{
    /// <summary>
    /// ‌
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class EFCoreRepository : IRepository
    {
        /// <summary>
        /// 
        /// </summary>
        [Required]
        private DbContext _db;
        /// <summary>
        /// 
        /// </summary>
        private IDbContextTransaction? _transaction = null;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public EFCoreRepository(DbContext context)
        {
            _db = context;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public long Insert<T>(T entity) where T : class, new()
        {
            _db.Set<T>().Add(entity);
            return _db.SaveChanges();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<long> InsertAsync<T>(T entity) where T : class, new()
        {
            await _db.Set<T>().AddAsync(entity);
            return await _db.SaveChangesAsync();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public long Update<T>(T entity) where T : class, new()
        {
            _db.Set<T>().Update(entity);
            return _db.SaveChanges();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<long> UpdateAsync<T>(T entity) where T : class, new()
        {
            await Task.Run(() =>
            {
                _db.Set<T>().Update(entity);
            });
            return await _db.SaveChangesAsync();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public long Delete<T>(T entity) where T : class, new()
        {
            _db.Set<T>().Remove(entity);
            return _db.SaveChanges();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public async Task<long> DeleteAsync<T>(T entity) where T : class, new()
        {
            await Task.Run(() =>
            {
                _db.Set<T>().Remove(entity);
            });
            return await _db.SaveChangesAsync();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IEnumerable<T> GetAll<T>() where T : class, new()
        {
            return _db.Set<T>().ToList();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public async Task<IEnumerable<T>> GetAllAsync<T>() where T : class, new()
        {
            return await _db.Set<T>().ToListAsync();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public T? GetById<T>(long id) where T : class, new() => _db.Set<T>().Find(id);
        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<T?> GetByIdAsync<T>(long id) where T : class, new() => await _db.Set<T>().FindAsync(id);

        #region 事务
        /// <summary>
        /// 同步开启事务
        /// </summary>
        public void BeginTransaction()
        {
            _transaction = _db.Database.BeginTransaction();
        }
        /// <summary>
        /// 同步提交事务
        /// </summary>
        public void CommitTransaction()
        {
            if (_transaction != null)
                _transaction.CommitAsync();
        }
        /// <summary>
        /// 同步回滚事务
        /// </summary>
        public void RollbackTransaction()
        {
            if (_transaction != null)
                _transaction.Rollback();
        }
        /// <summary>
        /// 异步开启事务
        /// </summary>
        public async Task BeginTransactionAsync()
        {
            _transaction = await _db.Database.BeginTransactionAsync();
        }
        /// <summary>
        /// 异步提交事务
        /// </summary>
        public async Task CommitTransactionAsync()
        {
            if (_transaction != null)
                await _transaction.CommitAsync();
        }
        /// <summary>
        /// 异步回滚事务
        /// </summary>
        public async Task RollbackTransactionAsync()
        {
            if (_transaction != null)
                await _transaction.RollbackAsync();
        }
        #endregion 事务
    }
}
